﻿using System;


namespace CSharpExt.Ref
{
    public class RefObject : IDisposable
    {
        #region Private Data

        public int refs;

        #endregion

        #region Operations

        public virtual void Dispose()
        {
            
        }

        #endregion
    }

    public struct RefPointer<T> where T : RefObject
    {
        #region Private Data

        private T _ptr;

        #endregion

        #region Constructor/Destructor

        public RefPointer(T ptr)
        {
            _ptr = ptr;
            AddRef();
        }

        public RefPointer(ref RefPointer<T> refp)
        {
            _ptr = refp.Get();
            AddRef();
        }

        public void Dispose()
        {
            Release();
        }

        #endregion

        #region Operations

        public RefPointer<T> Set(T ptr)
        {
            AddRef(ptr);
            Release();
            _ptr = ptr;
            return this;
        }

        public RefPointer<T> Set(ref RefPointer<T> refp)
        {
            refp.AddRef();
            Release();
            _ptr = refp.Get();
            return this;
        }

        public T Get()
        {
            return _ptr;
        }

        #endregion

        #region Implementation

        private void AddRef()
        {
            AddRef(_ptr);
        }

        private void Release()
        {
            Release(_ptr);
        }

        private static void AddRef(T ptr)
        {
            if (ptr != null)
                ptr.refs++;
        }

        private static void Release(T ptr)
        {
            if (ptr != null && 0 == --ptr.refs)
                ptr.Dispose();
        }

        #endregion
    }
}
